<?php

namespace app\command;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Log;
use Workerman\Lib\Timer;
use Workerman\Worker;

class Live extends Command
{
    protected function configure()
    {
        // 指令配置
        $this->setName('live');
        // 设置参数

    }

    protected function execute(Input $input, Output $output)
    {
    	// 指令输出
    	$output->writeln('live');
        //websocket协议
        $ws_worker = new Worker("websocket://0.0.0.0:1468");
        //启动4个进程对外提供服务
        $ws_worker->count = 10;
        //设置名称
        $ws_worker->name = 'ws_worker';
        //用户ID组
        $ws_worker->uidConnections = array();

        //启动
        $ws_worker->onWorkerStart = static function($ws_worker)
        {
            $time_interval = 2;
            Timer::add($time_interval, static function () use ($ws_worker) {
                echo "砰砰砰...\n";
            });

            $inner_text_worker = new Worker('text://127.0.0.1:5678');
            //这里的$connection是给推送者调用的
            $inner_text_worker->onMessage = static function ($connection, $buffer) {
                $connection->send( '你好欢迎你');
            };
            $inner_text_worker->listen();
        };

        // 当收到客户端发来的数据后返回hello $data给客户端
        $ws_worker->onMessage = static function($connection, $data)
        {
            if (empty($data)){
                $connection->send('数据提交错误');
                return false;
            }
            //在控制台打印客户端发送过来的消息
            $data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
            if (!isset($data['room_id'], $data['type'],$data['uid'])){
                $connection->send('参数错误!');
                return false;
            }
            $checkInfo = self::checkLogin($data['uid']);
            if (empty($checkInfo)){
                $connection->send('登录失效重新登录!');
                return false;
            }

            switch ($data['type']) {
                //登录绑定
                case 'login':
                    self::init($data , $connection , $checkInfo);
                    break;
                case 'sendMessage':
                    if (!isset($data['message'])){
                        $connection->send('参数错误!');
                        return false;
                    }
                    //向所有连接推送消息
                    self::broadcast($data['message'] , $checkInfo);
                    break;
                case 'sendLive':
                    if (!isset($data['message'])){
                        $connection->send('输出输入错误!');
                        return  false;
                    }
                    //直播间聊天发消息
                    self::sendMessageByLive($data['room_id'],$data['message'],$checkInfo);
                    break;
            }
            return true;
        };

        // 连接绑定通信ID
//        $ws_worker->onConnect = static function($connection)
//        {
//            $connection->send($connection->id.'来了');
//        };

        // 退出连接
        $ws_worker->onClose = static function ($connection) {
            global $ws_worker;
            if (isset($connection->roomId)){
                foreach($ws_worker->uidConnections[$connection->roomId] as $sen) {
                    $sen->send($connection->nick.'走了');
                }
                //退出关闭链接
                if ($connection->uid){
                    redis()->zRem('LiveOnlineUsers:'.$connection->roomId , $connection->info);
                    redis()->close();
                    unset($ws_worker->uidConnections[$connection->roomId][$connection->uid]);
                }
            }
        };
        // 运行worker
        Worker::runAll();
    }

    /*
 * $room_id 直播间ID
 * $message 消息内容
 * 直播间聊天循环推送在直播间的用户
 * $uid 用户ID
 */
    public static function  sendMessageByLive($room_id, $message ,$info): bool{
        global $ws_worker;
        if(empty($room_id) || empty($message)){
            return false;
        }
        //验证用户数据
        if (empty($info)){
            return  false;
        }
        //需要遍历在本直播间用户给每个用户推送聊天内容
        if (isset($ws_worker->uidConnections[$room_id])){
            foreach ($ws_worker->uidConnections[$room_id] as $connection) {
                $redisKey = 'imroomlog:'.$room_id;
                $setData = [
                    'uid'   => $info['id'],
                    'nick' => $info['nick'],
                    'content' => $message,
                    'toid' => $room_id,
                    'dates'=>date('Y-m-d H:i:s'),
                    'portrait'=>$info['portrait'],
                ];
                try {
                    try {
                        $redisData = json_encode($setData, JSON_THROW_ON_ERROR);
                    } catch (\JsonException $e) {
                        \think\facade\Log::info('Exception sendMessageByLiveEvent:JsonException' . $e->getMessage());
                    }
                    redis()->lPush($redisKey, $redisData);
                    redis()->close();
                } catch (\RedisException $e) {
                    \think\facade\Log::info('Exception sendMessageByLiveEvent: ' . $e->getMessage());
                }
                $connection->send($redisData);
            }
        }

        return false;
    }

    // 向所有验证的用户推送数据
    public static function broadcast($message ,$info): void
    {
        global $ws_worker;
        foreach($ws_worker->uidConnections as $conn) {
            $redisKey = 'imroomlog';
            $setData = [
                'nick' => $info['nick'],
                'content' => $message,
                'dates'=>date('Y-m-d H:i:s'),
                'portrait'=>$info['portrait'],
            ];
            try {
                $redisData = json_encode($setData, JSON_THROW_ON_ERROR);
            } catch (\JsonException $e) {
                Log::info('InfoERROR2'.$e->getMessage());
            }
            try {
                redis()->lPush($redisKey, $redisData);
                redis()->close();
            } catch (\RedisException $e) {
                Log::info('InfoERROR3'.$e->getMessage());
            }
            $conn->send($redisData);
        }
    }

    public static function checkLogin($uid): array
    {
        try {
            $info = redis()->get('userInfo:'.$uid);
            if (empty($info)){
                return [];
            }
            try {
                $info = json_decode($info, true, 512, JSON_THROW_ON_ERROR);
                $info['id'] = $uid;
            } catch (\JsonException $e) {
                Log::info('InfoERROR'.$e->getMessage());
            }

            return $info;
        } catch (\RedisException $e) {
            Log::info('checkLoginRedisException'.$e->getMessage());
        }
        return [];
    }

    public static function init($data , $conn , $info): void
    {
        global $ws_worker;
        $conn->roomId = $data['room_id'];
        $conn->uid  = $data['uid'];
        $conn->nick = $info['nick'];
        $ws_worker->uidConnections[$conn->roomId][$conn->uid] = $conn;
        try {
            redis()->zAdd('LiveOnlineUsers:' . $conn->roomId, $conn->uid, json_encode($info, JSON_THROW_ON_ERROR));
            redis()->close();
            $conn->info = json_encode($info, JSON_THROW_ON_ERROR);
            foreach($ws_worker->uidConnections[$conn->roomId] as $sen) {
                $sen->send($info['nick'].'进来了');
            }
        } catch (\JsonException $e) {
            Log::info('initJsonException'.$e->getMessage());
        } catch (\RedisException $e) {
            Log::info('RedisException'.$e->getMessage());
        }
    }
}
